(*
This file is part of the Lustre reader

* Copyright (c) 2010, Nicola Camuffo.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Nicola Camuffo, nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)


open Lustypes
open Opeval


let rec eval_static_expression (ex,tp) =

  let rec loop (ex,_) = match ex with
    E_BOOL _ | E_INT _ | E_REAL _ -> ex

    | E_CONST(id) -> get_constvalue id

    | E_AND(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _and a b
    | E_OR(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _or a b
    | E_XOR(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _xor a b
    | E_IMPL(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _impl a b
    | E_NOT(e) ->
      let a = loop e in
      _not a

    | E_EQ(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _eq a b
    | E_NEQ(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _uneq a b
    | E_LT(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _lt a b
    | E_LTE(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _lte a b
    | E_GT(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _gt a b
    | E_GTE(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _gte a b

    | E_PLUS(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _plus a b
    | E_MINUS(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _minus a b

    | E_MULT(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _mult a b
    | E_DIV(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _div a b
    | E_INTDIV(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _intdiv a b
    | E_MOD(e1,e2) ->
      let a = loop e1 in
      let b = loop e2 in
      _mod a b
    | E_UMINUS(e) ->
      let a = loop e in
      _uminus a

    | E_ITE(e1,e2,e3) ->
      if (_bool_value (loop e1)) then
	loop e2
      else
	loop e3

    | E_NOR(el) ->
      let vl = List.map (fun e -> _bool_value (loop e)) el in
      let v = List.fold_left (fun x y ->
	not (x || y)
      ) true vl 
      in
      E_BOOL(v)

    | E_EXCL(el) ->
      let nl = List.map (fun e -> if (_bool_value (loop e)) then 1 else 0) el in
      let n = List.fold_left (fun n1 n2 ->
	n1+n2
      ) 0 nl
      in
      E_BOOL(n=1)

    | e -> eval_nonstatic_expression e
  in
  
  let e = loop (ex,tp) in
  e,tp


and eval_nonstatic_expression ex = match ex with 
  _ -> raise (Expression_evaluation_exception "non static expression") (* shortcut: this function is developing afterwards *)




(*
  | E_WTE of _typed_expression * _typed_expression * _typed_expression

  | E_COERCE_TO_INT of _typed_expression
  | E_COERCE_TO_REAL of _typed_expression
  | E_COERCE_TO_BOOL of _typed_expression

  | E_PRE of _typed_expression
  | E_FOLLOWEDBY of _typed_expression * _typed_expression

  | E_WHEN of _typed_expression * _typed_expression
  | E_CURRENT of _typed_expression

  | E_TUPLE of _typed_expression list
  | E_STRUCT of (_sym * _typed_expression) list
  | E_LIST of _typed_expression list

  | E_ENUMSEL of _id * _sym (* type id, field name *)
  | E_STRUCTSEL of _typed_expression * _sym (* struct, field name *)
  | E_TUPLESEL of _typed_expression * _typed_expression * _typed_expression * _typed_expression (* tuple, inf, sup, step *)

  | E_NODE of _id * _typed_expression list (* node id, param list*)
  | E_OUTVAR of _typed_expression * _id (* node, var *)

  (* SCADE *)
(* | E_CASE of (_typed_expression * _typed_expression) list * _typed_expression *)
  | E_CONDACT of _typed_expression * _typed_expression * _typed_expression
  | E_FBY of _typed_expression * int * _typed_expression (* expr, num steps, init value *)
*)
  
